New Uses For FSAVE: Extended FSAVE
roy g biv / defjam
New Uses For FSAVE
roy g biv / defjam
-= defjam =-
since 1992
bringing you the viruses of tomorrow
today!
Former DOS/Win16 virus writer, author of several virus families, including
Ginger (see Coderz #1 zine for terrible buggy example, contact me for better
sources ;), and Virus Bulletin 9/95 for a description of what they called
Rainbow. Co-author of world's first virus using circular partition trick
(Orsam, coded with Prototype in 1993). Designer of world's first XMS swapping
virus (John Galt, coded by RT Fishel in 1995, only 30 bytes stub, the rest is
swapped out). Author of world's first virus using Thread Local Storage for
replication (Shrug, see Virus Bulletin 6/02 for a description, but they call
it Chiton), world's first virus using Visual Basic 5/6 language extensions for
replication (OU812), world's first Native executable virus (Chthon), world's
first virus using process co-operation to prevent termination (Gemini, see
Virus Bulletin 9/02 for a description), world's first virus using polymorphic
SMTP headers (JunkMail, see Virus Bulletin 11/02 for a description), world's
first viruses that can convert any data files to infectable objects (Pretext),
world's first 32/64-bit parasitic EPO .NET virus (Croissant, see Virus
Bulletin 11/04 for a description, but they call it Impanate), world's first
virus using self-executing HTML (JunkHTMaiL, see Virus Bulletin 7/03 for a
description), world's first virus for Win64 on Intel Itanium (Shrug, see Virus
Bulletin 6/04 for a description, but they call it Rugrat), world's first virus
for Win64 on AMD AMD64 (Shrug), world's first cross-infecting virus for Intel
IA32 and AMD AMD64 (Shrug), world's first viruses that infect Office
applications and script files using the same code (Macaroni, see Virus
Bulletin 11/05 for a description, but they call it Macar), world's first
viruses that can infect both VBS and JScript using the same code (ACDC, see
Virus Bulletin 11/05 for a description, but they call it Cada), world's first
virus that can infect CHM files (Charm, see Virus Bulletin 10/06 for a
description, but they call it Chamb), world's first IDA plugin virus (Hidan,
see Virus Bulletin 3/07 for a description), world's first viruses that use the
Microsoft Script Encoder to dynamically encrypt the virus body (Screed),
world's first virus for StarOffice and OpenOffice (Starbucks), world's first
virus IDC virus (ID10TiC), world's first polymorphic virus for Win64 on AMD
AMD64 (Boundary, see Virus Bulletin 12/06 for a description, but they call it
Bounds), world's first virus that can infect Intel-format and PowerPC-format
Mach-O files (MachoMan, see Virus Bulletin 01/07 for a description, but
they call it Macarena), world's first virus that uses Unicode escapes to
dynamically encrypt the virus body, world's first self-executing PIF (Spiffy),
world's first self-executing LNK (WeakLNK), world's first virus that uses
virtual code (Relock), and world's first virus to use FSAVE for instruction
reordering (Mimix). Author of various retrovirus articles (eg see Vlad #7 for
the strings that make your code invisible to TBScan). This is my sixteenth
virus for Win32. It is sad that this intro is longer than the text.
Extended FSAVE
Last time we talked about FPU for instruction reordering, but it is limited
because we cannot use arithmetic operations. We can avoid that problem if we
think about what else is stored in the FPU state: the MMX registers.
When FSAVE is executed, it will store the state of the FPU to the specified
memory location. The format of the state is known. It looks like this:
Offset Size Name Value
0x00 0x02 Control variable
0x02 0x02 Filler 0xffff
0x04 0x02 Status 0x0000
0x06 0x02 Filler 0xffff
0x08 0x02 Tag 0x0000 because we fill all registers
0x0a 0x02 Filler 0xffff
0x0c 0x04 LastEip variable
0x10 0x02 LastCS variable
0x12 0x02 Opcode variable (instruction & 0x03ff)
0x14 0x04 LastData variable
0x18 0x02 LastDS variable
0x1a 0x02 Filler 0xffff
0x1c 0x08 mm0 user-defined
0x24 0x02 pad 0xffff
0x26 0x08 mm1 user-defined
0x2e 0x02 pad 0xffff
0x30 0x08 mm2 user-defined
0x38 0x02 pad 0xffff
0x3a 0x08 mm3 user-defined
0x42 0x02 pad 0xffff
0x44 0x08 mm4 user-defined
0x4c 0x02 pad 0xffff
0x4e 0x08 mm5 user-defined
0x56 0x02 pad 0xffff
0x58 0x08 mm6 user-defined
0x60 0x02 pad 0xffff
0x62 0x08 mm7 user-defined
0x6a 0x02 pad 0xffff
Since the mm array is at the end and we can control it completely, I got the
idea to put instructions into it. Then if I use FSAVE at eip-0x21, so mm0
will be the next instruction to execute. It also means that I can write 0x40
bytes of code to memory using one instruction! One problem is that the MMX
registers are only 8 bytes long, but the FPU slots are 10 bytes long. It
means that we have only 7 bytes available per slot, if we use 0x80 to mask the
padding. MMX has another advantage, which is that the registers can be read
in any order. There are no restriction about the address of the values. It
is a nice coincidence that this sequence is exactly 0x21 bytes long, if byte
offsets are used for the memory loads. It means that there is no risk that
eax-0x21 will fall off the page and cause a fault.
load:
pop eax ;can be any register
movq mm0, qword ptr [eax + x0]
movq mm1, qword ptr [eax + x1]
movq mm2, qword ptr [eax + x2]
movq mm3, qword ptr [eax + x3]
movq mm4, qword ptr [eax + x4]
movq mm5, qword ptr [eax + x5]
movq mm6, qword ptr [eax + x6]
movq mm7, qword ptr [eax + x7]
;can be in any order
[here can be a decryptor for MMX registers]
fnsave byte ptr [eax - 21] ;overwrite call with mm0
start:
call load
[here can be values to load into mm array]
We do more, though. Since MMX registers can hold any value, we can perform
some operations on the registers, in the same way that we can do it for CPU
registers. Those operations can be the simple ones: add (paddq), sub (psubq),
xor (pxor), but it is enough.
A 0x40 bytes array might not sound very large, but we can put a nice decryptor
there, and make another one using the MMX registers. Since many AV emulators
do not support MMX properly, it doesn't even need to be very complex if they
can't run it.
Greets to friendly people (A-Z):
Active - Benny - izee - Malum - Obleak - Prototype - Ratter - Ronin -
RT Fishel - sars - SPTH - The Gingerbread Man - Ultras - uNdErX - Vallez -
Vecna - VirusBuster - Whitehead
rgb/defjam mar 2008
iam_rgb@hotmail.com